package cn.geekyspace.scanhive.adapter.controller.fxml;

import cn.geekyspace.scanhive.infrastructure.ui.UIExtendField;
import cn.geekyspace.scanhive.infrastructure.ui.UILogger;
import cn.geekyspace.scanhive.infrastructure.ui.UIPlcPortSettings;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToolBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Component
@RequiredArgsConstructor
public class ViewController {

    @FXML
    private BorderPane root;

    /*----------侧边栏----------*/
    /*-----串口设置-----*/
    @FXML
    private ComboBox<String> serialPortComboBox;  // 串口下拉框
    @FXML
    private ToggleButton connectToggleButton;     // 串口连接按钮
    /*-----菜单-----*/
    // 扫码展示
    @FXML
    private HBox scanButton;
    // 数据查询
    @FXML
    private HBox queryButton;
    /*-----扩展字段-----*/
    @FXML
    private TextField operatorUser;  // 操作员

    /*----------底部----------*/
    // 日志输出
    @FXML
    private Label logLabel;
    // pdf 预览舞台
    private static Stage pdfStage;

    // 注入 Spring 上下文
    private final ConfigurableApplicationContext context;
    // 缓存加载的 FXML 文件
    private final Map<String, Node> fxmlMap = new HashMap<>();

    // 注入UI组件
    private final UILogger uiLogger;
    private final UIPlcPortSettings uiPlcPortSettings;
    private final UIExtendField uiExtendField;

    //初始化时加载默认页面
    @FXML
    public void initialize() {
        // 注入UI-日志组件
        uiLogger.setLogLabel(logLabel);
        // 注入UI-PLC串口设置组件
        uiPlcPortSettings.setConnectToggleButton(connectToggleButton);
        uiPlcPortSettings.initSerialPortComboBox(serialPortComboBox);
        // 注入UI-扩展字段组件
        uiExtendField.setOperatorUser(operatorUser);

        // 加载并设置中心内容
        loadAndSetCenter("/fxml/ScanShow.fxml", "切换到扫描展示页面失败");
    }

    /*----------侧边栏----------*/
    /* PLC串口连接按钮点击事件 */
    @FXML
    void onPlcConnectButtonClick(ActionEvent event) {
        uiPlcPortSettings.handleConnectButtonClick();
    }


    /*-----菜单-----*/

    /**
     * 扫描菜单点击
     */
    @FXML
    public void onScanMenuClick() {
        if (scanButton.getStyleClass().contains("selected")) {
            return;  // 禁止重复点击
        }
        // 加载并设置中心内容
        loadAndSetCenter("/fxml/ScanShow.fxml", "切换到扫描展示页面失败");
        updateMenuButtonStyle(scanButton);
    }

    /**
     * 查询菜单点击
     */
    @FXML
    public void onQueryMenuClick() {
        if (queryButton.getStyleClass().contains("selected")) {
            return;  // 禁止重复点击
        }
        // 加载并设置中心内容
        loadAndSetCenter("/fxml/DataQuery.fxml", "切换到数据查询页面失败");
        updateMenuButtonStyle(queryButton);
    }

    /**
     * 加载 FXML 文件并设置为中心内容
     * @param fxmlFile     FXML 文件路径
     * @param errorMessage 错误日志信息
     */
    private void loadAndSetCenter(String fxmlFile, String errorMessage) {
        Node node = fxmlMap.get(fxmlFile);
        if (node != null) {
            root.setCenter(node);
        } else {
            FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFile));
            // 使用 Spring Bean 工厂管理控制器。
            loader.setControllerFactory(context::getBean);
            try {
                node = loader.load();
                fxmlMap.put(fxmlFile, node);
                root.setCenter(node);
            } catch (IOException e) {
                log.error("{}: {}", errorMessage, fxmlFile, e);
            }
        }
    }

    /**
     * 菜单切换样式类 "selected"
     */
    private void updateMenuButtonStyle(Node target) {
        // 清除所有按钮的 "selected" 样式
        scanButton.getStyleClass().remove("selected");
        queryButton.getStyleClass().remove("selected");

        // 为目标按钮添加 "selected" 样式
        if (!target.getStyleClass().contains("selected")) {
            target.getStyleClass().add("selected");
        }
    }


    /*----------底部----------*/
    @FXML
    public void scannerHelp(MouseEvent mouseEvent) {
        if (pdfStage != null && pdfStage.isShowing()) {
            // 如果窗口已存在且显示中，确保它显示在最上方
            pdfStage.setIconified(false);  // 如果窗口已最小化，则恢复显示
            pdfStage.toFront();  // 将窗口置于最前面
            pdfStage.requestFocus();  // 请求焦点，确保窗口活动
            return;
        }

        // 如果窗口已经关闭或不存在，则重新创建一个新的 Stage
        pdfStage = new Stage();

        // 设置窗口图标
        pdfStage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/img/geeky.png"))));
        // 加载 PDF 文件路径
        InputStream pdfInputStream = getClass().getResourceAsStream("/file/T27.pdf");  // 通过类路径加载 PDF 文件
        log.info("加载 PDF 文件路径: /file/T27.pdf");

        try {
            PDDocument document = PDDocument.load(pdfInputStream);
            PDFRenderer renderer = new PDFRenderer(document);

            // 渲染第一页为 BufferedImage 对象
            BufferedImage image = renderer.renderImageWithDPI(0, 300);
            Image fxImage = SwingFXUtils.toFXImage(image, null);
            ImageView imageView = new ImageView(fxImage);

            // 添加缩放功能
            Scale scale = new Scale(1.0, 1.0, 0, 0);
            imageView.getTransforms().add(scale);

            // 使用 ScrollPane 支持拖拽
            ScrollPane scrollPane = new ScrollPane(imageView);
            scrollPane.setPannable(true);

            // 创建工具栏按钮
            ToolBar toolBar = new ToolBar();
            Button btnZoomIn = new Button("放大");
            Button btnZoomOut = new Button("缩小");
            Button btnNextPage = new Button("下一页");
            Button btnPrevPage = new Button("上一页");

            toolBar.getItems().addAll(btnZoomIn, btnZoomOut, btnPrevPage, btnNextPage);

            // 工具栏按钮事件
            btnZoomIn.setOnAction(event -> {
                scale.setX(scale.getX() * 1.1);
                scale.setY(scale.getY() * 1.1);
            });

            btnZoomOut.setOnAction(event -> {
                scale.setX(scale.getX() / 1.1);
                scale.setY(scale.getY() / 1.1);
            });

            btnNextPage.setOnAction(event -> loadPage(renderer, document, imageView, 1)); // 下一页
            btnPrevPage.setOnAction(event -> loadPage(renderer, document, imageView, -1)); // 上一页

            // 布局设置
            BorderPane root = new BorderPane();
            root.setTop(toolBar);
            root.setCenter(scrollPane);

            Scene scene = new Scene(root, 900, 600);

            pdfStage.setTitle("PDF Viewer");
            pdfStage.setScene(scene);
            pdfStage.show();

            // 窗口关闭时释放 PDF 资源
            pdfStage.setOnCloseRequest(event -> {
                try {
                    document.close();
                } catch (IOException e) {
                    log.error("关闭 PDF 文档时发生错误: ", e);
                }
                pdfStage = null;  // 确保窗口关闭后 pdfStage 置为 null，便于重新创建
            });
        } catch (IOException e) {
            log.error("加载 PDF 文件失败: ", e);
        }
    }

    // 页码状态
    private int currentPage = 0;

    // 加载 PDF 页面
    private void loadPage(PDFRenderer renderer, PDDocument document, ImageView imageView, int pageOffset) {
        try {
            currentPage += pageOffset;
            currentPage = Math.max(0, Math.min(currentPage, document.getNumberOfPages() - 1));
            BufferedImage image = renderer.renderImageWithDPI(currentPage, 300);
            Image fxImage = SwingFXUtils.toFXImage(image, null);
            imageView.setImage(fxImage);
        } catch (IOException e) {
            log.error("加载页面失败: ", e);
        }
    }
}
